﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MCLuncher_CLI
{
    class Program
    {
        static async Task Main(string[] args)
        {
            while (true)
            {
                IntroduceAPP();
                Console.WriteLine("请选择您的操作:\n" +
                                "1. 检查JAVA\n" +
                                "Q. 退出");
                var input = Console.ReadLine()?.Trim().ToUpper();
                switch (input)
                {
                    case "1":
                        await CheckJava();
                        break;
                    case "Q":
                        Environment.Exit(0);
                        break;
                    default:
                        Console.WriteLine("请输入正确的选项");
                        Thread.Sleep(1000);
                        break;
                }
                Console.Clear();
            }
        }

        private static async Task CheckJava()
        {
            const int timeout = 5000;
            var processStartInfo = new ProcessStartInfo
            {
                FileName = "java",
                Arguments = "-version",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                CreateNoWindow = true
            };

            try
            {
                using var process = new Process { StartInfo = processStartInfo };
                var outputBuilder = new StringBuilder();
                var errorBuilder = new StringBuilder();

                process.OutputDataReceived += (_, e) => AppendIfNotEmpty(outputBuilder, e.Data);
                process.ErrorDataReceived += (_, e) => AppendIfNotEmpty(errorBuilder, e.Data);

                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();

                if (!process.WaitForExit(timeout))
                {
                    Console.WriteLine("Java检测超时");
                    return;
                }

                await Task.Delay(200); // 确保异步读取完成

                var output = outputBuilder.ToString();
                var error = errorBuilder.ToString();

                if (CheckJavaInstalled(output, error))
                {
                    Console.WriteLine($"Java已安装\n版本信息：\n{error.Trim()}");
                    PostCheckPrompt();
                    return;
                }

                Console.WriteLine("未检测到Java运行时环境");
                await OfferInstallOption();
            }
            catch (Exception ex) when (ex is FileNotFoundException || ex is Win32Exception)
            {
                Console.WriteLine("系统未找到java命令");
                await OfferInstallOption();
            }
        }

        private static void AppendIfNotEmpty(StringBuilder builder, string content)
        {
            if (!string.IsNullOrEmpty(content)) builder.AppendLine(content);
        }

        private static bool CheckJavaInstalled(string output, string error)
        {
            string[] versionKeywords = { "version", "运行时环境", "Runtime Environment" };
            return versionKeywords.Any(k =>
                error.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0 ||
                output.IndexOf(k, StringComparison.OrdinalIgnoreCase) >= 0);
        }

        private static void PostCheckPrompt()
        {
            Console.WriteLine("\n按任意键返回主菜单...");
            Console.ReadKey();
        }

        private static async Task OfferInstallOption()
        {
            while (true)
            {
                Console.WriteLine("是否安装JAVA？(Y/N)");
                string input = Console.ReadLine();

                if (input == "N")
                {
                    Console.WriteLine("安装已取消");
                    return;
                }

                if (input == "Y")
                {
                    await ShowInstallMenu();
                    return;
                }

                Console.WriteLine("无效输入，请重新选择");
            }
        }

        private static async Task ShowInstallMenu()
        {
            while (true)
            {
                Console.Clear();
                Console.WriteLine("请选择版本：\n" +
                                "1. Java 8 32位\n" +
                                "2. Java 8 64位\n" +
                                "3. Java 17 32位\n" +
                                "4. Java 17 64位\n" +
                                "5. Java 21 64位\n" +
                                "0. 取消安装");

                var input = Console.ReadLine()?.Trim();
                switch (input)
                {
                    case "1":
                        await InstallJava("8", "x86");
                        return;
                    case "2":
                        await InstallJava("8", "x64");
                        return;
                    case "3":
                        await InstallJava("17", "x86");
                        return;
                    case "4":
                        await InstallJava("17", "x64");
                        return;
                    case "5":
                        await InstallJava("21", "x64");
                        return;
                    case "0":
                        Console.WriteLine("安装已取消");
                        return;
                    default:
                        Console.WriteLine("无效输入，请重新选择");
                        await Task.Delay(1000);
                        break;
                }
            }
        }

        private static async Task InstallJava(string version, string bit)
        {
            Console.WriteLine("开始Java安装流程...");
            var urlMap = new Dictionary<(string, string), string>
            {
                { ("8", "x86"), "https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x32/windows/OpenJDK8U-jdk_x86-32_windows_hotspot_8u442b06.msi" },
                { ("8", "x64"), "https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/windows/OpenJDK8U-jdk_x64_windows_hotspot_8u442b06.msi" },
                { ("17", "x86"), "https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x32/windows/OpenJDK17U-jdk_x86-32_windows_hotspot_17.0.14_7.msi" },
                { ("17", "x64"), "https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x64/windows/OpenJDK17U-jdk_x64_windows_hotspot_17.0.14_7.msi" },
                { ("21", "x64"), "https://mirrors.tuna.tsinghua.edu.cn/Adoptium/21/jdk/x64/windows/OpenJDK21U-jdk_x64_windows_hotspot_21.0.6_7.msi" }
            };

            if (!urlMap.TryGetValue((version.ToLower(), bit.ToLower()), out var url))
            {
                Console.WriteLine($"不支持版本 {version} {bit}");
                return;
            }

            var tempFile = Path.Combine(Path.GetTempPath(), Path.GetFileName(url));
            try
            {
                Console.WriteLine($"\n下载目标文件：{Path.GetFileName(url)}");
                await DownloadWithBrowserHeaders(url, tempFile);
                await InstallPackage(tempFile);
                Console.WriteLine("\n安装已完成！请注意：");
                Console.WriteLine("1. 可能需要重新启动本程序才能检测到新安装的Java");
                Console.WriteLine("2. 如果安装失败，请尝试以管理员权限运行本程序");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"操作失败：{ex.Message}");
            }
            finally
            {
                CleanupFile(tempFile);
            }

            Console.WriteLine("\n按任意键返回主菜单...");
            Console.ReadKey();
        }

        private static async Task DownloadWithBrowserHeaders(string url, string savePath)
        {
            using var client = new HttpClient(new HttpClientHandler
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                MaxAutomaticRedirections = 3
            });

            client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
            client.Timeout = TimeSpan.FromMinutes(3);

            using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
            response.EnsureSuccessStatusCode();

            using var stream = await response.Content.ReadAsStreamAsync();
            using var fileStream = new FileStream(savePath, FileMode.Create);

            var totalBytes = response.Content.Headers.ContentLength ?? -1L;
            var buffer = new byte[8192];
            var totalRead = 0L;
            var lastUpdate = Stopwatch.StartNew();

            while (true)
            {
                var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
                if (bytesRead == 0) break;

                await fileStream.WriteAsync(buffer, 0, bytesRead);
                totalRead += bytesRead;

                if (lastUpdate.ElapsedMilliseconds > 200 || totalRead == totalBytes)
                {
                    Console.Write($"\r下载进度: {Math.Round((double)totalRead / totalBytes * 100, 1)}% | " +
                                $"\t已下载: {FormatSize(totalRead)}/{FormatSize(totalBytes)}");
                    lastUpdate.Restart();
                }
            }
            Console.WriteLine();
        }

        private static string FormatSize(long bytes)
        {
            string[] units = { "B", "KB", "MB", "GB" };
            var unitIndex = 0;
            var size = bytes;

            while (size >= 1024 && unitIndex < units.Length - 1)
            {
                size /= 1024;
                unitIndex++;
            }

            return $"{size:0.0} {units[unitIndex]}";
        }

        private static async Task InstallPackage(string msiPath)
        {
            if (!IsAdministrator())
            {
                Console.WriteLine("安装需要管理员权限，请右键以管理员身份运行程序");
                return;
            }

            using var process = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "msiexec",
                    Arguments = $"/i \"{msiPath}\" /qn /norestart",
                    UseShellExecute = false,
                    CreateNoWindow = true
                }
            };

            Console.WriteLine("\n正在安装...（可能需要5-10分钟）");
            process.Start();

            while (!process.WaitForExit(5000))
            {
                Console.WriteLine("仍在安装中，请稍候...");
            }
            await Task.Run(() => process.WaitForExit());
            if (process.ExitCode != 0)
            {
                throw new Exception($"安装失败，错误代码: {process.ExitCode}");
            }
        }

        private static bool IsAdministrator()
        {
            return new WindowsPrincipal(WindowsIdentity.GetCurrent())
                .IsInRole(WindowsBuiltInRole.Administrator);
        }

        private static void CleanupFile(string path)
        {
            try
            {
                File.Delete(path);
                Console.WriteLine("已清理临时文件");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"清理失败: {ex.Message}");
            }
        }

        private static void IntroduceAPP()
        {
            Console.Clear();
            var assembly = Assembly.GetExecutingAssembly();
            Console.WriteLine($"欢迎使用 {assembly.GetName().Name}\n版本: {assembly.GetName().Version}\n");
        }
    }
}